//策略模式工具类
let toolObject = {
    bind(node,vm,attrKey,express){
        node.setAttribute(attrKey,this.getValue(vm,express))
        node.removeAttribute('v-bind:'+attrKey)
        new Watcher(node,express,vm,(value)=>{
            node.setAttribute(attrKey,this.getValue(vm,express))
            node.removeAttribute('v-bind:'+attrKey)
        })
    },
    text(node,vm){
        //1、从高级语法中获取对应的属性名
        //2、从data中获取对应属性的值替换到对应节点上
        let targetStr = node.textContent
        node.textContent = node.textContent.replace(/\{\{(.*?)\}\}/g,(arg,$1)=>{
            new Watcher(node,$1,vm,(value)=>{
                this.changeValue(node,targetStr,vm)
            })
            return this.getValue(vm,$1)
        })
    },
    html(node,vm,express){
        node.innerHTML = this.getValue(vm,express)
        new Watcher(node,express,vm,(value)=>{
            node.innerHTML = value
            this.setValue(vm,express,value)
        })
    },
    model(node,vm,express){
        node.value = this.getValue(vm,express)
        new Watcher(node,express,vm,()=>{
            node.removeEventListener('input',myInput)
            node.value = this.getValue(vm,express)
            node.addEventListener('input',myInput.bind(this))
        })
        node.addEventListener('input',myInput.bind(this))
        function myInput(e){
            this.setValue(vm,express,e.target.value)
        }
    },
    on(node,vm,eventName,express){
        console.log(node,vm,eventName,express)
        node.addEventListener(eventName,vm.$options.methods[express].bind(vm))
    },//count.math
    setValue(vm,express,value){
        let arr = express.split('.')
        arr.reduce((obj,current,index)=>{
            if(index === arr.length-1){
                return obj[current] = value
            }else{
                return obj = obj[current]
            }
        },vm)
    },
    getValue(vm,express){
        let arr = express.split('.')
        let value = arr.reduce((obj,current)=>{
           return obj = obj[current]
        },vm)
        return value
    },
    changeValue(node,targetStr,vm){
        vm.$update()
        node.textContent = targetStr.replace(/\{\{(.*?)\}\}/g,(arg,$1)=>{
            return this.getValue(vm,$1)
        })
    }
}

class Vue{
    constructor(options){
        this.$options = options
        this.$el = options.el
        this.$update = options.update
        
        //属性代理
        new Observer(this)
        options.created.call(this)
        //获取容器
        this.$container = this.returnHtmlContainer(this.$el)
        //获取容器内的dom树对应的文档碎片
        this.$fragment = this.returnFragment()
        //编译
        this.compile(this.$fragment)
        //当文档碎片被编译完成之后，追加到页面对应容器中
        this.$container.appendChild(this.$fragment)
        options.mounted.call(this)
       
    }
    returnHtmlContainer(querySelector){
       return document.querySelector(querySelector)?document.querySelector(querySelector):document.body
    }
    returnFragment(){
        //let nodes = this.$container.childNodes
        //console.log(nodes,'----')
        //创建空的文档碎片
        let fragment = document.createDocumentFragment()
        //console.log(this.$container.firstChild)
        let tmp;
        while(tmp = this.$container.firstChild){
            fragment.appendChild(tmp)
        }
        return fragment
    }
    compile(element){
        //遍历文档碎片的子节点进行转换
        //1、从高级语法中获取对应的属性名
        //2、从data中获取对应属性的值替换到对应节点上
        element.childNodes.forEach((node)=>{
            if(this.isElement(node)){
                this.compileElement(node,this)
            }
            if(this.isTextNode(node)){
                this.compileText(node,this)
            }
        })
        
    }
    compileElement(node){
        //做一个递归处理
        if(node.childNodes.length){
            this.compile(node)
        }
        //获取该节点所有属性的集合
        let attrList = node.attributes;
        //遍历所有属性，找到需要我们处理的属性进行处理，以v-开头的属性
        [...attrList].forEach((attributeItem)=>{
            //name为属性名  value为属性值
            let {name,value} = attributeItem;
            //以v-开头的属性都需要我们处理
            if(name.startsWith('v-')){
                //console.log(name,value,'----')
                
                if(name.startsWith('v-on')){
                    //事件绑定 v-on:click
                    toolObject['on'](node,this,name.split(':')[1],value)
                }else{
                   
                    if(name.startsWith('v-bind')){//'v-bind:id'
                        toolObject['bind'](node,this,name.slice(7),value)
                    }else{
                         //通过innerHTML覆盖元素内容
                        toolObject[name.slice(2)](node,this,value)
                    }
                }
            }
            
        })
        
    }
    compileText(node,vm){/* {{username}} */
        toolObject['text'](node,vm)
        //1、从高级语法中获取对应的属性名
        //2、从data中获取对应属性的值替换到对应节点上
        // node.textContent = node.textContent.replace(/\{\{(.*?)\}\}/,(arg,$1)=>{
        //     return vm.$options.data[$1]
        // })
    }
    isElement(node){
        return node.nodeType === 1
    }
    isTextNode(node){
        return node.nodeType === 3
    }
}
console.log(123123,"_________________________________")